#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time      :2021/7/15 16:33
# @Author    :cjw
"""邮件发送"""
from os.path import join
from typing import Optional, AnyStr

import emails
from emails.template import JinjaTemplate

from app.core.config import settings
from app.utils.log import logger


def send_email(email_to: str, subject_template: AnyStr, html_template: AnyStr,
               environment: Optional[dict] = None) -> None:
    """
    发送邮件
    :param email_to: 收件人信息
    :param subject_template: 邮件主题
    :param html_template: 邮件html内容模板
    :param environment: 邮件模板展示的数据
    :return:
    """
    assert settings.EMAILS_ENABLED, '邮件发送参数未配置齐全'

    # 邮件内容
    message = emails.Message(
        subject=JinjaTemplate(subject_template),
        html=JinjaTemplate(html_template),
        mail_from=(settings.EMAILS_FROM_NAME, settings.EMAILS_FROM_EMAIL)
    )

    # 邮件发送smtp参数配置
    smtp_options = {'host': settings.SMTP_HOST, 'port': settings.SMTP_PORT}
    if settings.SMTP_SSL:
        smtp_options['ssl'] = True
    if settings.SMTP_USER:
        smtp_options['user'] = settings.SMTP_USER
    if settings.SMTP_PASSWORD:
        smtp_options['password'] = settings.SMTP_PASSWORD

    # 发送邮件
    response = message.send(to=email_to, render=environment, smtp=smtp_options)
    logger.info(f'邮件接收人：{email_to}, 发送电子邮件结果: {response}')


def send_test_email(email_to: str = settings.EMAIL_TEST_USER) -> None:
    """
    发送邮件测试
    :param email_to: 收件人
    :return:
    """
    project_name = settings.PROJECT_NAME
    subject = f'{project_name} - 测试邮件'
    with open(join(settings.EMAIL_TEMPLATES_DIR, 'test_email.html'), encoding='utf-8') as f:
        template_str = f.read()
    send_email(
        email_to=email_to,
        subject_template=subject,
        html_template=template_str,
        environment={'project_name': settings.PROJECT_NAME, 'email': email_to}
    )


def send_reset_password_email(email_to: str, email: str, token):
    """
    发送密码重置邮件
    :param email_to: 收件人
    :param email:  重置密码的用户邮箱
    :param token: 令牌
    :return:
    """
    # 构建邮件标题，获取邮件模板内容
    subject = f'{settings.PROJECT_NAME} - 重置账号的登录密码 {email}'
    with open(join(settings.EMAIL_TEMPLATES_DIR, 'reset_password.html'), encoding='utf-8') as f:
        template_str = f.read()

    # 判断token的数据格式
    if hasattr(token, 'decode'):
        use_token = token.decode()
    else:
        use_token = token

    # 拼接密码重置链接地址，发送邮件
    link = f'{settings.SERVER_HOST}{settings.API_V1_STR}/reset-password?token={use_token}'
    send_email(
        email_to=email_to,
        subject_template=subject,
        html_template=template_str,
        environment={
            'project_name': settings.PROJECT_NAME,
            'username': email,
            'valid_hours': settings.EMAIL_RESET_TOKEN_EXPIRE_HOURS,
            'link': link
        }
    )


def send_new_account_email(email_to: str, username: str, password: str) -> None:
    """
    新帐户发送电子邮件
    :param email_to: 邮件接收人
    :param username: 用户名
    :param password: 密码
    :return:
    """
    subject = f'{settings.PROJECT_NAME} - 新账号 {username}'
    with open(join(settings.EMAIL_TEMPLATES_DIR, 'new_account.html'), encoding='utf-8') as f:
        template_str = f.read()
    link = settings.SERVER_HOST
    send_email(
        email_to=email_to,
        subject_template=subject,
        html_template=template_str,
        environment={
            'project_name': settings.PROJECT_NAME,
            'username': username,
            'password': password,
            'email': email_to,
            'link': link,
        }
    )
